package com.alibaba.service.impl;

import com.alibaba.mapper.UserMapper;
import com.alibaba.model.entity.User;
import com.alibaba.model.param.LoginRequest;
import com.alibaba.service.UserService;
import com.alibaba.utils.BizException;
import com.alibaba.utils.CodeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;

/**
 *
 * @author ZhouYaDong
 * @date 2025/9/25
 * @description
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public void sendLoginCode(String username) {
        // 根据查询用户信息
        User user = findByUsername(username);
        Long userId = user.getId();
        // 生成验证码
        String loginCode = CodeUtil.generate6DigitCode();
        // 拼接RedisKey
        String redisKey = "login_code-" + userId;
        // 将验证码存入 Redis，并设置验证码过期时间为 5 分钟
        redisTemplate.opsForValue().set(redisKey,loginCode, Duration.ofMinutes(5));
        // 发送验证码
        log.info("向用户{}发送验证码{}，写入Redis，redisKsy:{}",username,loginCode,redisKey);
    }

    @Override
    public String login(LoginRequest request) {
        // 1️⃣ 查询用户信息
        User user = findByUsername(request.getUsername());
        if (user == null) {
            throw new BizException("用户名或密码错误");
        }

        // 2️⃣ 验证密码
        if (!user.getPassword().equals(request.getPassword())) {
            throw new BizException("用户名或密码错误");
        }

        // 3️⃣ 验证码校验
        String redisKey = "login_code:" + user.getId();
        String codeInRedis = (String) redisTemplate.opsForValue().get(redisKey);

        // 验证码错误计数key
        String errorCountKey = "login_code_error_count:" + user.getId();
        Integer errorCount = (Integer) redisTemplate.opsForValue().get(errorCountKey);
        if (errorCount == null) {
            errorCount = 0;
        }

        // 判断验证码是否正确
        if (codeInRedis == null || !codeInRedis.equals(request.getCode())) {
            // 增加错误次数
            errorCount++;
            redisTemplate.opsForValue().set(errorCountKey, errorCount, Duration.ofMinutes(15)); // 错误计数15分钟有效
            if (errorCount >= 5) { // 错误次数达到阈值
                // 可选择冻结账户或限制再次请求验证码
                throw new BizException("验证码错误次数过多，请稍后再试");
            }
            log.info("验证码错误，用户输入的验证码：{}，Redis中的验证码：{}", request.getCode(), codeInRedis);
            throw new BizException("验证码错误或已过期");
        }

        // 4️⃣ 登录成功，删除验证码和错误计数
        redisTemplate.delete(redisKey);
        redisTemplate.delete(errorCountKey);

        log.info("用户{}登录成功", request.getUsername());
        return "登录成功";
    }

    @Override
    public User findByUsername(String username) {
        val queryWrapper1 = new QueryWrapper<User>().eq("username", username);
        val user = userMapper.selectOne(queryWrapper1);
        if (user == null) {
            throw new BizException("用户不存在");
        }
        return user;
    }

}
